From 465b7f441b57a0cef5eda102c829623f8fba7fb1 Mon Sep 17 00:00:00 2001 From: Cody Russell Date: Wed, 9 May 2007 15:46:41 +0000 Subject: [PATCH] Refactored arrow border size, visible area, and sensitive area calculations svn path=/trunk/; revision=17808 --- ChangeLog | 19 +++ gtk/gtkmenu.c | 317 +++++++++++++++++++++++++++++--------------------- 2 files changed, 203 insertions(+), 133 deletions(-) diff --git a/ChangeLog b/ChangeLog index e9f0b12ec0..d5f902a0fc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2007-05-09 Cody Russell + + * gtk/gtkmenu.c: + (get_arrows_border): New function to calculate the border sizes needed + for the scroll arrows. + (get_arrows_visible_area): New function to calculate the arrows visible + area. + (get_arrows_sensitive_area): New function to calculate the arrows + sensitive area. + (gtk_menu_paint): Refactored code to calculate the border sizes needed + for the scroll arrows into get_arrows_border and the code to calculate + the visible area into get_arrows_visible_area. + (gtk_menu_handle_scrolling): Refactored arrow sensitive calculations + to get_arrows_sensitive_area. + (gtk_menu_realize, gtk_menu_size_allocate, gtk_menu_scroll_by, + gtk_menu_position, gtk_menu_scroll_to, gtk_menu_scroll_item_visible, + get_visible_size, get_menu_height, gtk_menu_real_move_scroll): Update + callers. (From #436533, Tommi Komulainen) + 2007-05-09 Kristian Rietveld * gtk/gtktreeview.c (gtk_tree_view_key_press), diff --git a/gtk/gtkmenu.c b/gtk/gtkmenu.c index 71de7d7c2e..242488960b 100644 --- a/gtk/gtkmenu.c +++ b/gtk/gtkmenu.c @@ -2006,6 +2006,21 @@ gtk_menu_style_set (GtkWidget *widget, } } +static void +get_arrows_border (GtkMenu *menu, GtkBorder *border) +{ + guint scroll_arrow_height; + + gtk_widget_style_get (GTK_WIDGET (menu), + "scroll-arrow-vlength", &scroll_arrow_height, + NULL); + + border->top = menu->upper_arrow_visible ? scroll_arrow_height : 0; + border->bottom = menu->lower_arrow_visible ? scroll_arrow_height : 0; + + border->left = border->right = 0; +} + static void gtk_menu_realize (GtkWidget *widget) { @@ -2017,7 +2032,7 @@ gtk_menu_realize (GtkWidget *widget) GList *children; guint vertical_padding; guint horizontal_padding; - guint scroll_arrow_height; + GtkBorder arrow_border; g_return_if_fail (GTK_IS_MENU (widget)); @@ -2048,7 +2063,6 @@ gtk_menu_realize (GtkWidget *widget) gtk_widget_style_get (GTK_WIDGET (menu), "vertical-padding", &vertical_padding, "horizontal-padding", &horizontal_padding, - "scroll-arrow-vlength", &scroll_arrow_height, NULL); attributes.x = border_width + widget->style->xthickness + horizontal_padding; @@ -2056,14 +2070,10 @@ gtk_menu_realize (GtkWidget *widget) attributes.width = MAX (1, widget->allocation.width - attributes.x * 2); attributes.height = MAX (1, widget->allocation.height - attributes.y * 2); - if (menu->upper_arrow_visible) - { - attributes.y += scroll_arrow_height; - attributes.height -= scroll_arrow_height; - } - - if (menu->lower_arrow_visible) - attributes.height -= scroll_arrow_height; + get_arrows_border (menu, &arrow_border); + attributes.y += arrow_border.top; + attributes.height -= arrow_border.top; + attributes.height -= arrow_border.bottom; menu->view_window = gdk_window_new (widget->window, &attributes, attributes_mask); gdk_window_set_user_data (menu->view_window, menu); @@ -2284,7 +2294,6 @@ gtk_menu_size_allocate (GtkWidget *widget, gint width, height; guint vertical_padding; guint horizontal_padding; - gint scroll_arrow_height; g_return_if_fail (GTK_IS_MENU (widget)); g_return_if_fail (allocation != NULL); @@ -2299,7 +2308,6 @@ gtk_menu_size_allocate (GtkWidget *widget, gtk_widget_style_get (GTK_WIDGET (menu), "vertical-padding", &vertical_padding, "horizontal-padding", &horizontal_padding, - "scroll-arrow-vlength", &scroll_arrow_height, NULL); x = GTK_CONTAINER (menu)->border_width + widget->style->xthickness + horizontal_padding; @@ -2314,14 +2322,15 @@ gtk_menu_size_allocate (GtkWidget *widget, if (menu_shell->active) gtk_menu_scroll_to (menu, menu->scroll_offset); - if (menu->upper_arrow_visible && !menu->tearoff_active) + if (!menu->tearoff_active) { - y += scroll_arrow_height; - height -= scroll_arrow_height; - } + GtkBorder arrow_border; - if (menu->lower_arrow_visible && !menu->tearoff_active) - height -= scroll_arrow_height; + get_arrows_border (menu, &arrow_border); + y += arrow_border.top; + height -= arrow_border.top; + height -= arrow_border.bottom; + } if (GTK_WIDGET_REALIZED (widget)) { @@ -2435,36 +2444,61 @@ gtk_menu_size_allocate (GtkWidget *widget, } } +static void +get_arrows_visible_area (GtkMenu *menu, + GdkRectangle *border, + GdkRectangle *upper, + GdkRectangle *lower, + gint *arrow_space) +{ + GtkWidget *widget = GTK_WIDGET (menu); + guint vertical_padding; + guint horizontal_padding; + gint scroll_arrow_height; + + gtk_widget_style_get (widget, + "vertical-padding", &vertical_padding, + "horizontal-padding", &horizontal_padding, + "scroll-arrow-vlength", &scroll_arrow_height, + NULL); + + border->x = GTK_CONTAINER (widget)->border_width + widget->style->xthickness + horizontal_padding; + border->y = GTK_CONTAINER (widget)->border_width + widget->style->ythickness + vertical_padding; + gdk_drawable_get_size (widget->window, &border->width, &border->height); + + upper->x = border->x; + upper->y = border->y; + upper->width = border->width - 2 * border->x; + upper->height = scroll_arrow_height; + + lower->x = border->x; + lower->y = border->height - border->y - scroll_arrow_height; + lower->width = border->width - 2 * border->x; + lower->height = scroll_arrow_height; + + *arrow_space = scroll_arrow_height - 2 * widget->style->ythickness; +} + static void gtk_menu_paint (GtkWidget *widget, GdkEventExpose *event) { GtkMenu *menu; GtkMenuPrivate *priv; - gint width, height; - gint border_x, border_y; - guint vertical_padding; - guint horizontal_padding; - gint scroll_arrow_height; + GdkRectangle border; + GdkRectangle upper; + GdkRectangle lower; + gint arrow_space; g_return_if_fail (GTK_IS_MENU (widget)); menu = GTK_MENU (widget); priv = gtk_menu_get_private (menu); - gtk_widget_style_get (GTK_WIDGET (menu), - "vertical-padding", &vertical_padding, - "horizontal-padding", &horizontal_padding, - "scroll-arrow-vlength", &scroll_arrow_height, - NULL); - - border_x = GTK_CONTAINER (widget)->border_width + widget->style->xthickness + horizontal_padding; - border_y = GTK_CONTAINER (widget)->border_width + widget->style->ythickness + vertical_padding; - gdk_drawable_get_size (widget->window, &width, &height); + get_arrows_visible_area (menu, &border, &upper, &lower, &arrow_space); if (event->window == widget->window) { - gint arrow_space = scroll_arrow_height - 2 * widget->style->ythickness; gint arrow_size = 0.7 * arrow_space; gtk_paint_box (widget->style, @@ -2481,10 +2515,10 @@ gtk_menu_paint (GtkWidget *widget, priv->upper_arrow_state, GTK_SHADOW_OUT, &event->area, widget, "menu", - border_x, - border_y, - width - 2 * border_x, - scroll_arrow_height); + upper.x, + upper.y, + upper.width, + upper.height); gtk_paint_arrow (widget->style, widget->window, @@ -2493,8 +2527,8 @@ gtk_menu_paint (GtkWidget *widget, &event->area, widget, "menu_scroll_arrow_up", GTK_ARROW_UP, TRUE, - (width - arrow_size ) / 2, - border_y + widget->style->ythickness + (arrow_space - arrow_size)/2, + upper.x + (upper.width - arrow_size) / 2, + upper.y + widget->style->ythickness + (arrow_space - arrow_size) / 2, arrow_size, arrow_size); } @@ -2505,10 +2539,10 @@ gtk_menu_paint (GtkWidget *widget, priv->lower_arrow_state, GTK_SHADOW_OUT, &event->area, widget, "menu", - border_x, - height - border_y - scroll_arrow_height, - width - 2*border_x, - scroll_arrow_height); + lower.x, + lower.y, + lower.width, + lower.height); gtk_paint_arrow (widget->style, widget->window, @@ -2517,26 +2551,30 @@ gtk_menu_paint (GtkWidget *widget, &event->area, widget, "menu_scroll_arrow_down", GTK_ARROW_DOWN, TRUE, - (width - arrow_size) / 2, - height - border_y - scroll_arrow_height + - widget->style->ythickness + (arrow_space - arrow_size)/2, + lower.x + (lower.width - arrow_size) / 2, + lower.y + widget->style->ythickness + (arrow_space - arrow_size) / 2, arrow_size, arrow_size); } } else if (event->window == menu->bin_window) { - gint y = -border_y + menu->scroll_offset; + gint y = -border.y + menu->scroll_offset; - if (menu->upper_arrow_visible && !menu->tearoff_active) - y -= scroll_arrow_height; + if (!menu->tearoff_active) + { + GtkBorder arrow_border; + + get_arrows_border (menu, &arrow_border); + y -= arrow_border.top; + } gtk_paint_box (widget->style, menu->bin_window, GTK_STATE_NORMAL, GTK_SHADOW_OUT, &event->area, widget, "menu", - - border_x, y, - width, height); + - border.x, y, + border.width, border.height); } } @@ -2998,14 +3036,12 @@ gtk_menu_scroll_by (GtkMenu *menu, gint offset; gint view_width, view_height; gboolean double_arrows; - gint scroll_arrow_height; + GtkBorder arrow_border; widget = GTK_WIDGET (menu); offset = menu->scroll_offset + step; - gtk_widget_style_get (GTK_WIDGET (menu), - "scroll-arrow-vlength", &scroll_arrow_height, - NULL); + get_arrows_border (menu, &arrow_border); double_arrows = get_double_arrows (menu); @@ -3015,7 +3051,7 @@ gtk_menu_scroll_by (GtkMenu *menu, * screen space than just scrolling to the top. */ if (!double_arrows) - if ((step < 0) && (offset < scroll_arrow_height)) + if ((step < 0) && (offset < arrow_border.top)) offset = 0; /* Don't scroll over the top if we weren't before: */ @@ -3030,13 +3066,13 @@ gtk_menu_scroll_by (GtkMenu *menu, /* Don't scroll past the bottom if we weren't before: */ if (menu->scroll_offset > 0) - view_height -= scroll_arrow_height; + view_height -= arrow_border.top; /* When both arrows are always shown, reduce * view height even more. */ if (double_arrows) - view_height -= scroll_arrow_height; + view_height -= arrow_border.bottom; if ((menu->scroll_offset + view_height <= widget->requisition.height) && (offset + view_height > widget->requisition.height)) @@ -3152,6 +3188,47 @@ gtk_menu_scroll (GtkWidget *widget, return TRUE; } +static void +get_arrows_sensitive_area (GtkMenu *menu, + GdkRectangle *upper, + GdkRectangle *lower) +{ + gint width, height; + gint border; + guint vertical_padding; + gint win_x, win_y; + gint scroll_arrow_height; + + gdk_drawable_get_size (GTK_WIDGET (menu)->window, &width, &height); + + gtk_widget_style_get (GTK_WIDGET (menu), + "vertical-padding", &vertical_padding, + "scroll-arrow-vlength", &scroll_arrow_height, + NULL); + + border = GTK_CONTAINER (menu)->border_width + + GTK_WIDGET (menu)->style->ythickness + vertical_padding; + + gdk_window_get_position (GTK_WIDGET (menu)->window, &win_x, &win_y); + + if (upper) + { + upper->x = win_x; + upper->y = win_y; + upper->width = width; + upper->height = scroll_arrow_height + border; + } + + if (lower) + { + lower->x = win_x; + lower->y = win_y + height - border - scroll_arrow_height; + lower->width = width; + lower->height = scroll_arrow_height + border; + } +} + + static void gtk_menu_handle_scrolling (GtkMenu *menu, gint x, @@ -3161,47 +3238,27 @@ gtk_menu_handle_scrolling (GtkMenu *menu, { GtkMenuShell *menu_shell; GtkMenuPrivate *priv; - gint width, height; - gint border; GdkRectangle rect; gboolean in_arrow; gboolean scroll_fast = FALSE; - guint vertical_padding; gint top_x, top_y; - gint win_x, win_y; gboolean touchscreen_mode; - gint scroll_arrow_height; priv = gtk_menu_get_private (menu); menu_shell = GTK_MENU_SHELL (menu); - gdk_drawable_get_size (GTK_WIDGET (menu)->window, &width, &height); - g_object_get (gtk_widget_get_settings (GTK_WIDGET (menu)), "gtk-touchscreen-mode", &touchscreen_mode, NULL); - gtk_widget_style_get (GTK_WIDGET (menu), - "vertical-padding", &vertical_padding, - "scroll-arrow-vlength", &scroll_arrow_height, - NULL); - - border = GTK_CONTAINER (menu)->border_width + - GTK_WIDGET (menu)->style->ythickness + vertical_padding; - gdk_window_get_position (menu->toplevel->window, &top_x, &top_y); x -= top_x; y -= top_y; - gdk_window_get_position (GTK_WIDGET (menu)->window, &win_x, &win_y); - /* upper arrow handling */ - rect.x = win_x; - rect.y = win_y; - rect.width = width; - rect.height = scroll_arrow_height + border; + get_arrows_sensitive_area (menu, &rect, NULL); in_arrow = FALSE; if (menu->upper_arrow_visible && !menu->tearoff_active && @@ -3301,10 +3358,7 @@ gtk_menu_handle_scrolling (GtkMenu *menu, /* lower arrow handling */ - rect.x = win_x; - rect.y = win_y + height - border - scroll_arrow_height; - rect.width = width; - rect.height = scroll_arrow_height + border; + get_arrows_sensitive_area (menu, NULL, &rect); in_arrow = FALSE; if (menu->lower_arrow_visible && !menu->tearoff_active && @@ -3778,7 +3832,6 @@ gtk_menu_position (GtkMenu *menu) GdkScreen *screen; GdkScreen *pointer_screen; GdkRectangle monitor; - gint scroll_arrow_height; g_return_if_fail (GTK_IS_MENU (menu)); @@ -3787,10 +3840,6 @@ gtk_menu_position (GtkMenu *menu) screen = gtk_widget_get_screen (widget); gdk_display_get_pointer (gdk_screen_get_display (screen), &pointer_screen, &x, &y, NULL); - - gtk_widget_style_get (GTK_WIDGET (menu), - "scroll-arrow-vlength", &scroll_arrow_height, - NULL); /* We need the requisition to figure out the right place to * popup the menu. In fact, we always need to ask here, since @@ -3986,7 +4035,12 @@ gtk_menu_position (GtkMenu *menu) } if (scroll_offset > 0) - scroll_offset += scroll_arrow_height; + { + GtkBorder arrow_border; + + get_arrows_border (menu, &arrow_border); + scroll_offset += arrow_border.top; + } gtk_window_move (GTK_WINDOW (GTK_MENU_SHELL (menu)->active ? menu->toplevel : menu->tearoff_window), x, y); @@ -4040,7 +4094,7 @@ gtk_menu_scroll_to (GtkMenu *menu, guint vertical_padding; guint horizontal_padding; gboolean double_arrows; - gint scroll_arrow_height; + GtkBorder arrow_border; widget = GTK_WIDGET (menu); @@ -4061,7 +4115,6 @@ gtk_menu_scroll_to (GtkMenu *menu, gtk_widget_style_get (GTK_WIDGET (menu), "vertical-padding", &vertical_padding, "horizontal-padding", &horizontal_padding, - "scroll-arrow-vlength", &scroll_arrow_height, NULL); double_arrows = get_double_arrows (menu); @@ -4088,11 +4141,13 @@ gtk_menu_scroll_to (GtkMenu *menu, if (!menu->upper_arrow_visible || !menu->lower_arrow_visible) gtk_widget_queue_draw (GTK_WIDGET (menu)); - view_height -= 2 * scroll_arrow_height; - y += scroll_arrow_height; - menu->upper_arrow_visible = menu->lower_arrow_visible = TRUE; + get_arrows_border (menu, &arrow_border); + y += arrow_border.top; + view_height -= arrow_border.top; + view_height -= arrow_border.bottom; + if (offset <= 0) priv->upper_arrow_state = GTK_STATE_INSENSITIVE; else if (priv->upper_arrow_state == GTK_STATE_INSENSITIVE) @@ -4149,8 +4204,9 @@ gtk_menu_scroll_to (GtkMenu *menu, last_visible = menu->upper_arrow_visible; menu->upper_arrow_visible = offset > 0; - if (menu->upper_arrow_visible) - view_height -= scroll_arrow_height; + /* upper_arrow_visible may have changed, so requery the border */ + get_arrows_border (menu, &arrow_border); + view_height -= arrow_border.top; if ((last_visible != menu->upper_arrow_visible) && !menu->upper_arrow_visible) @@ -4168,8 +4224,9 @@ gtk_menu_scroll_to (GtkMenu *menu, last_visible = menu->lower_arrow_visible; menu->lower_arrow_visible = offset < menu_height - view_height; - if (menu->lower_arrow_visible) - view_height -= scroll_arrow_height; + /* lower_arrow_visible may have changed, so requery the border */ + get_arrows_border (menu, &arrow_border); + view_height -= arrow_border.bottom; if ((last_visible != menu->lower_arrow_visible) && !menu->lower_arrow_visible) @@ -4184,8 +4241,7 @@ gtk_menu_scroll_to (GtkMenu *menu, } } - if (menu->upper_arrow_visible) - y += scroll_arrow_height; + y += arrow_border.top; } /* Scroll the menu: */ @@ -4263,14 +4319,12 @@ gtk_menu_scroll_item_visible (GtkMenuShell *menu_shell, { guint vertical_padding; gboolean double_arrows; - gint scroll_arrow_height; y = menu->scroll_offset; gdk_drawable_get_size (GTK_WIDGET (menu)->window, &width, &height); gtk_widget_style_get (GTK_WIDGET (menu), "vertical-padding", &vertical_padding, - "scroll-arrow-vlength", &scroll_arrow_height, NULL); double_arrows = get_double_arrows (menu); @@ -4286,23 +4340,25 @@ gtk_menu_scroll_item_visible (GtkMenuShell *menu_shell, } else { - arrow_height = 0; - if (menu->upper_arrow_visible && !menu->tearoff_active) - arrow_height += scroll_arrow_height; - if (menu->lower_arrow_visible && !menu->tearoff_active) - arrow_height += scroll_arrow_height; + GtkBorder arrow_border; + + arrow_height = 0; + + get_arrows_border (menu, &arrow_border); + if (!menu->tearoff_active) + arrow_height = arrow_border.top + arrow_border.bottom; if (child_offset + child_height > y + height - arrow_height) { arrow_height = 0; if ((!last_child && !menu->tearoff_active) || double_arrows) - arrow_height += scroll_arrow_height; + arrow_height += arrow_border.bottom; y = child_offset + child_height - height + arrow_height; if (((y > 0) && !menu->tearoff_active) || double_arrows) { /* Need upper arrow */ - arrow_height += scroll_arrow_height; + arrow_height += arrow_border.top; y = child_offset + child_height - height + arrow_height; } /* Ignore the enter event we might get if the pointer is on the menu @@ -4654,21 +4710,20 @@ get_visible_size (GtkMenu *menu) { GtkWidget *widget = GTK_WIDGET (menu); GtkContainer *container = GTK_CONTAINER (menu); - gint scroll_arrow_height; gint menu_height = (widget->allocation.height - 2 * (container->border_width + widget->style->ythickness)); - - gtk_widget_style_get (GTK_WIDGET (menu), - "scroll-arrow-vlength", &scroll_arrow_height, - NULL); - if (menu->upper_arrow_visible && !menu->tearoff_active) - menu_height -= scroll_arrow_height; - if (menu->lower_arrow_visible && !menu->tearoff_active) - menu_height -= scroll_arrow_height; + if (!menu->tearoff_active) + { + GtkBorder arrow_border; + get_arrows_border (menu, &arrow_border); + menu_height -= arrow_border.top; + menu_height -= arrow_border.bottom; + } + return menu_height; } @@ -4721,20 +4776,18 @@ get_menu_height (GtkMenu *menu) { gint height; GtkWidget *widget = GTK_WIDGET (menu); - gint scroll_arrow_height; - gtk_widget_style_get (GTK_WIDGET (menu), - "scroll-arrow-vlength", &scroll_arrow_height, - NULL); - height = widget->requisition.height; height -= (GTK_CONTAINER (widget)->border_width + widget->style->ythickness) * 2; - if (menu->upper_arrow_visible && !menu->tearoff_active) - height -= scroll_arrow_height; + if (!menu->tearoff_active) + { + GtkBorder arrow_border; - if (menu->lower_arrow_visible && !menu->tearoff_active) - height -= scroll_arrow_height; + get_arrows_border (menu, &arrow_border); + height -= arrow_border.top; + height -= arrow_border.bottom; + } return height; } @@ -4746,11 +4799,6 @@ gtk_menu_real_move_scroll (GtkMenu *menu, gint page_size = get_visible_size (menu); gint end_position = get_menu_height (menu); GtkMenuShell *menu_shell = GTK_MENU_SHELL (menu); - gint scroll_arrow_height; - - gtk_widget_style_get (GTK_WIDGET (menu), - "scroll-arrow-vlength", &scroll_arrow_height, - NULL); switch (type) { @@ -4790,11 +4838,14 @@ gtk_menu_real_move_scroll (GtkMenu *menu, { GtkWidget *new_child; gboolean new_upper_arrow_visible = menu->upper_arrow_visible && !menu->tearoff_active; + GtkBorder arrow_border; + + get_arrows_border (menu, &arrow_border); if (menu->scroll_offset != old_offset) step = menu->scroll_offset - old_offset; - step -= (new_upper_arrow_visible - old_upper_arrow_visible) * scroll_arrow_height; + step -= (new_upper_arrow_visible - old_upper_arrow_visible) * arrow_border.top; new_child = child_at (menu, child_offset + step); if (new_child) -- 2.30.2